package com.lhy.framework.beans.factory.support;

import com.lhy.framework.beans.BeansException;
import com.lhy.framework.beans.factory.DisposableBean;
import com.lhy.framework.beans.factory.factory.SingletonBeanRegistry;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @ClassName DefaultSingletonBeanRegistry
 * @Description
 * @Author lihaiyang
 * @Date 2022/9/8 22:24
 * @Version 1.0
 */
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {

    /**
     * Internal marker for a null singleton object:
     * used as marker value for concurrent Maps (which don't support null values).
     */
    protected static final Object NULL_OBJECT = new Object();

    private Map<String, Object> singletonObjects = new HashMap<>();

    private final Map<String, DisposableBean> disposableBeanMap = new HashMap<>();

    /**
     * 获取单例对象
     * @param beanName
     * @return
     */
    @Override
    public Object getSingleton(String beanName) {
        return singletonObjects.get(beanName);
    }

    @Override
    public void registerSingleton(String beanName, Object singletonObject) {
        singletonObjects.put(beanName, singletonObject);
    }

    /**
     * 添加单例bean对象
     * @param beanName
     * @param object
     */
    public void addSingleton(String beanName, Object object) {
        singletonObjects.put(beanName, object);
    }

    public void registerDisposableBean(String beanName, DisposableBean disposableBean) {
        disposableBeanMap.put(beanName, disposableBean);
    }

    public void destroySingletons() {
        Set<String> disposableBeans = disposableBeanMap.keySet();
        Object[] disposableBeanNames = disposableBeans.toArray();

        for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
            Object beanName = disposableBeanNames[i];
            DisposableBean disposableBean = disposableBeanMap.remove(beanName);
            try {
                disposableBean.destroy();
            } catch (Exception e) {
                throw new BeansException("Destroy method on bean with name '" + beanName + "' throw an exception");
            }
        }
    }
}
